package cn.iocoder.yudao.framework.geo;

import cn.hutool.core.io.resource.ClassPathResource;

/**
 * 使用 GeoJSON 和 JTS（Java Topology Suite）根据经纬度找到所在的区域。
 * <a href="https://geo.datav.aliyun.com/areas_v3/bound/geojson?code=100000">中国边界</a>
 * <a href="https://geo.datav.aliyun.com/areas_v3/bound/geojson?code=100000_full">中国省界</a>
 * <a href="https://geo.datav.aliyun.com/areas_v3/bound/geojson?code=100000_full_city">中国市界</a>
 *
 * @author 山野羡民（1032694760@qq.com）
 * @since 2024/12/06
 * @link <a href="https://datav.aliyun.com/portal/school/atlas/area_selector">area selector</a>
 * @link <a href="https://geojson.hxkj.vip">geojson</a>
 */
public class GeoUtils {

    public static GeoParser.Region findRegion(String geoJsonResourcePath, double longitude, double latitude) {
        try {
            String geoJsonPath = new ClassPathResource(geoJsonResourcePath).getAbsolutePath();
            GeoParser geoParser = new GeoParser();
            geoParser.loadGeoJson(geoJsonPath);
            return geoParser.findRegion(longitude, latitude);
        } catch (Exception e) {
            e.printStackTrace(System.err);
            return new GeoParser.Region("", "", null);
        }
    }

    /**
     * 根据经纬度找到所在的省份，地理坐标系为`GCJ_02`
     *
     * @param longitude 经度
     * @param latitude  纬度
     * @return 行政区域
     */
    public static GeoParser.Region findProvince(double longitude, double latitude) {
        return findRegion("GeoJSON/100000.geoJson", longitude, latitude);
    }

    /**
     * 根据经纬度找到所在的城市，地理坐标系为`GCJ_02`
     *
     * @param longitude 经度
     * @param latitude  纬度
     * @return 行政区域
     */
    public static GeoParser.Region findCity(String provinceCode, double longitude, double latitude) {
        return findRegion("GeoJSON/100000/" + provinceCode + ".geoJson", longitude, latitude);
    }

    /**
     * 根据经纬度找到所在的区县，地理坐标系为`GCJ_02`
     *
     * @param longitude 经度
     * @param latitude  纬度
     * @return 行政区域
     */
    public static GeoParser.Region findCounty(String provinceCode, String cityCode, double longitude, double latitude) {
        return findRegion("GeoJSON/100000/" + provinceCode + "/" + cityCode + ".geoJson", longitude, latitude);
    }

    public static void main(String[] args) throws Exception {
        GeoParser.Region province = findProvince(116.4074, 39.9042);
        System.out.println("Found province: " + province.getName() + ", adcode: " + province.getAdcode());
        GeoParser.Region city = findCity(province.getAdcode(), 116.4074, 39.9042);
        System.out.println("Found city: " + city.getName() + ", adcode: " + city.getAdcode());
        GeoParser.Region county = findCounty(province.getAdcode(), city.getAdcode(), 116.4074, 39.9042);
        System.out.println("Found county: " + county.getName() + ", adcode: " + county.getAdcode());

        province = findProvince(106.688734, 26.568359);
        System.out.println("Found province: " + province.getName() + ", adcode: " + province.getAdcode());
        city = findCity(province.getAdcode(), 106.688734, 26.568359);
        System.out.println("Found city: " + city.getName() + ", adcode: " + city.getAdcode());
        county = findCounty(province.getAdcode(), city.getAdcode(), 106.688734, 26.568359);
        System.out.println("Found county: " + county.getName() + ", adcode: " + county.getAdcode());
    }

}